import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.MessageDigest;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

import sun.security.provider.MD5;

import com.sun.org.apache.xerces.internal.impl.dtd.XMLContentSpec.Provider;


public class TestEncrypt {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String infile = "secrets.txt";
		String outfile = "secrets.des";
		String password = "I AM A KEY";
		
		try{
			FileInputStream fin = new FileInputStream(infile);
			FileOutputStream fout = new FileOutputStream(outfile);
			
			// register the provider that implements the algorithm
			java.security.Provider sunJce = new com.sun.crypto.provider.SunJCE();
			Security.addProvider(sunJce);
			
			// create a key
			char[] pbeKeyData = password.toCharArray();
			PBEKeySpec pbeKeySpec = new PBEKeySpec(pbeKeyData);
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
			SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
			
			// use Data Encryption Standard
			Cipher pbe = Cipher.getInstance("PBEWithMD5AndDES");
			pbe.init(Cipher.ENCRYPT_MODE, pbeKey);
			CipherOutputStream cout = new CipherOutputStream(fout, pbe);
			
//			byte[] input = new byte[64];
//			while(true)
//			{
//				int bytesRead = fin.read(input);
//				if( bytesRead == -1)
//					break;
//				cout.write(input,0,bytesRead);
//			}
			
			cout.flush();
			cout.close();
//			fin.close();
			
			// another function to create MD5 digest
			int fileSize = fin.available();
			byte[] reads = new byte[fileSize];
			fin.read(reads, 0, fileSize);
			
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(reads);
			
			byte[] digest = md.digest();
			
			char hexDigits[] = {       // 用来将字节转换成 16 进制表示的字符
				     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',  'e', 'f'}; 
			char str[] = new char[16 * 2];   // 每个字节用 16 进制表示的话，使用两个字符，
			// 所以表示成 16 进制需要 32 个字符
			int k = 0;                                // 表示转换结果中对应的字符位置
			for (int i = 0; i < 16; i++) {          // 从第一个字节开始，对 MD5 的每一个字节
			            // 转换成 16 进制字符的转换
			byte byte0 = digest[i];                 // 取第 i 个字节
			str[k++] = hexDigits[byte0 >>> 4 & 0xf];  // 取字节中高 4 位的数字转换, 
			                        // >>> 为逻辑右移，将符号位一起右移
			str[k++] = hexDigits[byte0 & 0xf];            // 取字节中低 4 位的数字转换
			}
			String s = new String(str);                                 // 换后的结果转换为字符串
			fin.close();
			
		}
		catch(Exception ex)
		{
			System.err.println(ex);
		}
	}

}
